package com.daify.threadlearn.chapter01.order05;

import java.util.Map;
import java.util.concurrent.*;

/**
 * @author daify
 * @date 2019-06-10
 */
public class CacheFour<T,K> implements Computable<T,K> {

    private final Map<T,Future<K>> cache = new ConcurrentHashMap<T, Future<K>>();

    private final Computable<T,K> c;

    public CacheFour(Computable<T, K> c) {
        this.c = c;
    }

    @Override
    public K compute(final T arg) throws Exception {
        while (true) {
            Future<K> kFuture = cache.get(arg);
            if (kFuture == null) {
                Callable<K> eval = new Callable<K>() {
                    @Override
                    public K call() throws Exception {
                        return c.compute(arg);
                    }
                };

                FutureTask<K> futureTask = new FutureTask<K>(eval);
                kFuture = futureTask;
                cache.putIfAbsent(arg,kFuture);
                futureTask.run();
            }
            try {
                return kFuture.get();
            } catch (CancellationException e) {
                cache.remove(arg);
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            }
        }
    }
}
